//Grable Hook by Sonic1983
freeslot("MT_SPAWNSPINSPEED", "MT_SPINSPEED")

//local cv_startspeed = CV_RegisterVar({name = "f_startspeed", defaultvalue = "0", flags = CV_NETVAR, PossibleValue = CV_Unsigned, func = nil})
//local cv_accel = CV_RegisterVar({name = "f_accel", defaultvalue = "1", flags = CV_NETVAR, PossibleValue = CV_Unsigned, func = nil})

addHook("MobjSpawn", function(hook)
local mo = P_SpawnMobj(hook.x, hook.y, hook.z, MT_SPINSPEED)
hook.target = mo
mo.target = hook
end, MT_SPAWNSPINSPEED)

addHook("MobjThinker", function(base)
	if base
	and base.valid
	and base.type == MT_SPAWNSPINSPEED
	local hook = base.target
		if base.z < base.floorz+128*FRACUNIT
		base.z = base.floorz+128*FRACUNIT
		end
		if base.chain == nil
		base.chain = P_SpawnMobj(base.x, base.y, base.z, MT_BIGMACECHAIN)
		elseif base.chain
		and base.chain.valid
		local chain = base.chain
		local angle = R_PointToAngle2(base.x, base.y, hook.x, hook.y)
		local x = base.x+FixedMul(cos(angle), R_PointToDist2(base.x, base.y, hook.x, hook.y)/2)
		local y = base.y+FixedMul(sin(angle), R_PointToDist2(base.x, base.y, hook.x, hook.y)/2)
		local z
		base.chain.radius = base.radius
		base.chain.height = base.height
			if not (chain.flags & MF_NOCLIP)
			base.chain.flags = $1|(MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING)
			end
			if hook
			and hook.valid
				if hook.z < base.z
				z = base.z-P_AproxDistance(0, base.z-hook.z)/2
				else
				z = base.z+P_AproxDistance(0, base.z-hook.z)/2
				end
			end
		P_TeleportMove(chain, x, y, z)
		end
		/*if base.chain2 == nil
		base.chain2 = P_SpawnMobj(base.x, base.y, base.z, MT_BIGMACECHAIN)
		elseif base.chain2
		and base.chain2.valid
		local chain = base.chain2
		local x = hook.x+FixedMul(cos(hook.angle), R_PointToDist2(hook.x, hook.y, base.x, base.y)/2)
		local y = hook.y+FixedMul(sin(hook.angle), R_PointToDist2(hook.x, hook.y, base.x, base.y)/2)
		P_TeleportMove(chain, x, y, hook.z)
		end*/
		if hook
		and hook.valid
		hook.angle = base.angle
			if not hook.tracer
			P_TeleportMove(hook, base.x, base.y, base.z+base.height/4-114*FRACUNIT)
			end
		end
	end
end, MT_SPAWNSPINSPEED)

local function CheckAngle(mo, collide, drawangle)
local angle
	if mo.player and drawangle
	angle = mo.player.drawangle-R_PointToAngle2(mo.x-mo.momx, mo.y-mo.momy, collide.x-collide.momx, collide.y-collide.momy)
	else
	angle = mo.angle+ANGLE_180-R_PointToAngle2(mo.x-mo.momx, mo.y-mo.momy, collide.x-collide.momx, collide.y-collide.momy)
	end
	if angle >= 180*ANG1
	angle = $- 360*ANG1
	elseif angle <= -180*ANG1
	angle = $+360*ANG1
	end
return angle
end

local function SetAngle(mo, mo2)
	if abs(CheckAngle(mo, mo2, true)) > ANGLE_45
	return false
	else
	return true
	end
end

addHook("TouchSpecial", function(hook, mo)
	if hook
	and hook.valid
	and hook.type == MT_SPINSPEED
		if mo
		and mo.valid
		and mo.player
		and mo.player.playerstate == PST_LIVE
			if mo.player.speed > 12*FRACUNIT
			and not mo.spingrab
			and not hook.tracer
			and not hook.cooldown
				if SetAngle(mo, hook)
				and SetAngle(hook, mo)
				mo.spingrab = true
				mo.autospin = true
				P_ResetPlayer(mo.player)
				hook.tracer = mo
				hook.rotatespeed = mo.player.speed+8*FRACUNIT
				S_StartSound(mo, sfx_spin)
				end
			end
		end
	end
return true
end, MT_SPINSPEED)

local function ZRotate(mo)
local hspeed = 0
local vspeed = mo.rotatespeed/4
local radius = 114*FRACUNIT
mo.rotatez = $1 + FixedAngle(vspeed)
local md = mo.rotatez
local fa = mo.angle+ANGLE_180
local x = mo.target.x + FixedMul(FixedMul(sin(md),cos(fa)),radius)
local y = mo.target.y + FixedMul(FixedMul(sin(md),sin(fa)),radius)
local z = mo.target.z + FixedMul(cos(md),radius) + mo.target.height/2 - mo.height/2
P_TeleportMove(mo, x, y, z)
end

addHook("MobjThinker", function(hook)
	if hook
	and hook.valid
	and hook.type == MT_SPINSPEED
		if hook.rotatespeed == nil
		hook.rotatespeed = 0
		end
		if hook.rotatez == nil
		hook.rotatez = 0
		end
		if hook.invert_z == nil
		hook.invert_z = false
		end
		if hook.cooldown == nil
		hook.cooldown = 0
		end
		if hook.cooldown > 0
		hook.cooldown = $1 - 1
		end
		if hook.rotatespeed >= 80*FRACUNIT
		hook.rotatespeed = 80*FRACUNIT
		end
		if hook.tracer
		and hook.tracer.valid
		ZRotate(hook)
		P_TeleportMove(hook.tracer, hook.x, hook.y, hook.z+hook.height/4)
		hook.tracer.momx = 0
		hook.tracer.momy = 0
		hook.tracer.momz = 0
		hook.tracer.state = S_PLAY_ROLL
		hook.tracer.player.pflags = $1|PF_SPINNING
		hook.tracer.player.drawangle = hook.angle
		//P_SpawnThokMobj(hook.tracer.player)
		local thok = P_SpawnMobjFromMobj(hook.tracer, 0, 0, 0, MT_THOK)
		thok.color = hook.tracer.color
			if hook.z+FRACUNIT > hook.target.z+114*FRACUNIT
			hook.invert_z = true
			end
			if hook.invert_z
			hook.rotatespeed = $1 + FRACUNIT*2
				if hook.z-hook.height/2 <= hook.target.z-hook.target.height/4-114*FRACUNIT
				P_InstaThrust(hook.tracer, hook.angle, hook.rotatespeed)
				P_SetObjectMomZ(hook.tracer, -hook.rotatespeed/4)
				hook.tracer.state = S_PLAY_ROLL
				hook.tracer.player.pflags = $1|PF_SPINNING
				hook.tracer.spingrab = false
				hook.cooldown = 5
				hook.tracer.autospin = true
				hook.tracer = nil
				S_StartSound(hook, sfx_zoom)
				end
			else
			hook.rotatespeed = $1 - FRACUNIT/2
				if hook.rotatespeed < 0
				hook.rotatespeed = $1 - FRACUNIT/2
					if hook.z-hook.height/2 <= hook.target.z-hook.target.height/4-114*FRACUNIT
					P_InstaThrust(hook.tracer, hook.angle, hook.rotatespeed)
					P_SetObjectMomZ(hook.tracer, hook.rotatespeed/4)
					hook.tracer.state = S_PLAY_ROLL
					hook.tracer.player.pflags = $1|PF_SPINNING
					hook.tracer.spingrab = false
					hook.cooldown = 5
					hook.tracer.autospin = true
					hook.tracer = nil
					S_StartSound(hook, sfx_zoom)
					end
				end
			end
		else
		hook.rotatespeed = 0
		hook.rotatez = ANGLE_180
		hook.invert_z = false
		end
	end
end, MT_SPINSPEED)

addHook("PlayerThink", function(player)
	if player.mo
	and player.mo.valid
	and player.playerstate == PST_LIVE
		if player.mo.spingrab == nil
		player.mo.spingrab = false
		end
		if player.mo.autospin == nil
		player.mo.autospin = false
		end
		if player.mo.autospin
		and P_IsObjectOnGround(player.mo)
		player.pflags = $1|PF_SPINNING
		player.mo.state = S_PLAY_ROLL
		player.mo.autospin = false
		end
	end
end)

addHook("PreThinkFrame", function()
	for player in players.iterate
		if player.mo
		and player.mo.valid
		and player.playerstate == PST_LIVE
			if player.mo.spingrab == true
			player.cmd.forwardmove = 0
			player.cmd.sidemove = 0
			player.cmd.buttons = 0
			end
		end
	end
end)